unit uLoadExcelThread;

interface

uses
  System.Classes, System.SysUtils, System.Variants, System.Win.ComObj,
  Vcl.ComCtrls, Vcl.StdCtrls, Vcl.ExtCtrls, uBaseCompThread, Vcl.Dialogs,
  System.UITypes;

type
//  TLoadExcelProcess = class(TThread)
  TLoadExcelProcess = class(TBaseCompThread)
  private
    { Private declarations }
    FilePaths: TStrings;
    ErrorMessage: string;
    function VarToCurr(Value: Variant): Currency;
    procedure ErrorDialog;
  protected
    procedure Execute; override;
  public
    constructor Create(CreateSuspended: Boolean; FilePaths: TStrings;
      ProgressBar: TProgressBar; StatusBar: TStatusBar; PageControl:
      TPageControl; LoadExcelFileBtn, UpdateBtn: TButton; InsPanel: TPanel); overload;
  end;

var
  LoadExcelProcess: TLoadExcelProcess;

implementation

uses
  uCompDM;

// TLoadExcelProcess
// Поток для парсинга файла Excel

constructor TLoadExcelProcess.Create(CreateSuspended: Boolean; FilePaths:
  TStrings; ProgressBar: TProgressBar; StatusBar: TStatusBar; PageControl:
  TPageControl; LoadExcelFileBtn, UpdateBtn: TButton; InsPanel: TPanel);
begin
  inherited Create(CreateSuspended, ProgressBar, StatusBar, PageControl,
    LoadExcelFileBtn, UpdateBtn, InsPanel);

  Self.FilePaths := FilePaths;
end;

function TLoadExcelProcess.VarToCurr(Value: Variant): Currency;
begin
  // Преобразование Variant в Currency с изменением разделителя
  Result := StrToCurr(CompDM.UpdateDecimalSeparator(VarToStr(Value)));
end;

procedure TLoadExcelProcess.ErrorDialog;
begin
  MessageDlg(ErrorMessage, mtError, [mbOK], 0);
end;

procedure TLoadExcelProcess.Execute;
var
  ExcelApp, WorkSheet, FData: OLEVariant;
  i, Rows, StartIndex: Integer;
  PredprId: Int64;
  PredprName, FileName, ShortName: string;
  dopunn: Variant;
begin
  // Создание объекта для работы с XLS/XLSX
  ExcelApp := CreateOleObject('Excel.Application');

  with CompDM do
  try
    Self.Enabled := False;
    Synchronize(ChangeControlAvailability);

    Self.PBStyle := pbstMarquee;
    Synchronize(SetProgressBarStyle);

    CrExcelTemp.ExecSQL;

    for FileName in Self.FilePaths do
    begin
      StartIndex := 3;
      ShortName := Copy(FileName, LastDelimiter('\', FileName) + 1, Length(FileName)
        - LastDelimiter('\', FileName));

      Self.StatusText := 'Загрузка файла ' + ShortName;
      Synchronize(SetStatusBarText);

      ExcelApp.Workbooks.Open(FileName);

      // Возможно WorkSheets будет определяется как ошибка, но синтаксис рабочий и правильный
      WorkSheet := ExcelApp.Workbooks[1].WorkSheets[1];
      Rows := WorkSheet.UsedRange.Rows.Count;
      FData := WorkSheet.UsedRange.Value;

      Self.StatusText := 'Вставка записей ' + ShortName + ' в таблицу...';
      Synchronize(SetStatusBarText);

      // Поиск номера первой строки с информацией
      for i := 1 to Rows do
        if (Length(Trim(VarToStr(FData[i, 1]))) <> 0) and (Trim(VarToStr(FData[i,
          1])) <> 'Код страны поставщика') then
        begin
          StartIndex := i;
          Break;
        end;

      // Цикл считывания информации из файла и вставка во временную таблицу
      for i := StartIndex to Rows do
      begin
        if Length(Trim(VarToStr(FData[i, 3]))) = 0 then
        begin
          PredprId := StrToInt64(Trim(VarToStr(FData[i, 2])) + '0000');
          PredprName := Trim(VarToStr(FData[i, 2])) + ' - ' + Trim(VarToStr(FData[i, 4]));
        end
        else
        begin
          PredprId := StrToInt64(Trim(VarToStr(FData[i, 2])) + Trim(VarToStr(FData[i, 3])));
          PredprName := Trim(VarToStr(FData[i, 2])) + ' ' + Trim(VarToStr(FData[i,
            3])) + ' - ' + Trim(VarToStr(FData[i, 4]));
        end;

        if Length(Trim(VarToStr(FData[i, 10]))) = 0 then
          dopunn := null
        else
          dopunn := Trim(VarToStr(FData[i, 10]));

        try
          InsertExcelTemp(PredprId, PredprName, VarToStr(FData[i, 15]), VarToStr
            (FData[i, 38]), 'П', VarToStr(FData[i, 11]), VarToStr(FData[i, 14]),
            VarToDateTime(FData[i, 20]), VarToDateTime(FData[i, 39]), 5,
            VarToCurr(FData[i, 43]), VarToCurr(FData[i, 41]), VarToCurr(FData[i, 44]), dopunn);
        except
          on eIns: EInsExcelTempException do
          begin
            Self.ErrorMessage := eIns.Message;
            Synchronize(ErrorDialog);
          end;
          on eConv: EVariantTypeCastError do
          begin
            Self.ErrorMessage := 'Ошибка преобразования в строку в ЭСЧФ ' + VarToStr(FData[i, 15]);
            Synchronize(ErrorDialog);
          end;
        end;
      end;

      ExcelApp.Workbooks.Close;
    end;
  finally
    Self.StatusText := 'Выгрузка файла камерального контроля...';
    Synchronize(SetStatusBarText);

    ExcelApp.Quit;
    VarClear(FData);
    VarClear(WorkSheet);
    VarClear(ExcelApp);
  end;

  Self.StatusText := 'Обработка завершена';
  Synchronize(SetStatusBarText);

  Self.Enabled := True;
  Synchronize(ChangeControlAvailability);

  Self.PBStyle := pbstNormal;
  Synchronize(SetProgressBarStyle);
end;

end.

